/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Universal charset detector code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2001
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *          BYVoid <byvoid.kcp@gmail.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
#include "uchardet.h"
#include "nscore.h"
#include "nsUniversalDetector.h"
#include <string>
#include <unistd.h>
#include <jni.h>

using std::string;

#define NUMBER_OF_SAMPLES   (128)

class HandleUniversalDetector : public nsUniversalDetector
{
protected:
	string m_charset;

public:
    HandleUniversalDetector()
    : nsUniversalDetector(NS_FILTER_ALL)
    {
        m_charset = "";
    }

    virtual ~HandleUniversalDetector()
    {}

    virtual void Report(const char* charset)
    {
        m_charset = charset;
    }

    virtual void Reset()
    {
        nsUniversalDetector::Reset();
        m_charset = "";
    }

    const char* GetCharset() const
    {
        return m_charset.c_str();
    }
};

uchardet_t uchardet_new()
{
    return reinterpret_cast<uchardet_t> (new HandleUniversalDetector());
}

void uchardet_delete(uchardet_t ud)
{
    delete reinterpret_cast<HandleUniversalDetector*>(ud);
}

int uchardet_handle_data(uchardet_t ud, const char * data, size_t len)
{
    nsresult ret = reinterpret_cast<HandleUniversalDetector*>(ud)->HandleData(data, (PRUint32)len);
    return (ret != NS_OK);
}

void uchardet_data_end(uchardet_t ud)
{
    reinterpret_cast<HandleUniversalDetector*>(ud)->DataEnd();
}

void uchardet_reset(uchardet_t ud)
{
    reinterpret_cast<HandleUniversalDetector*>(ud)->Reset();
}

const char* uchardet_get_charset(uchardet_t ud)
{
    return reinterpret_cast<HandleUniversalDetector*>(ud)->GetCharset();
}

const char *fileEncodingString(const char *fileName, int &error)
{
    error = 0;
    const char *encodingStr = NULL;

    FILE* file;
    char buf[NUMBER_OF_SAMPLES];
    int len;
    uchardet_t ud;

    /* 打开被检测文本文件，并读取一定数量的样本字符 */
    file = fopen(fileName, "rt");
    len = fread(buf, sizeof(char), NUMBER_OF_SAMPLES, file);
    fclose(file);

    /* 通过样本字符分析文本编码 */
    ud = uchardet_new();
    if(uchardet_handle_data(ud, buf, len) != 0) /* 如果样本字符不够，那么有可能导致分析失败 */
    {
        printf("分析编码失败！\n");
        error = -1;
        return encodingStr;
    }
    uchardet_data_end(ud);
    encodingStr = uchardet_get_charset(ud);
    printf("文本的编码方式是%s。\n", encodingStr);  /* 获取并打印文本编码 */
    uchardet_delete(ud);

    return encodingStr;
}

//extern "C" {
// jint Java_com_example_pthread_Ptrhead_cjjtest (JNIEnv *env, jclass thiz);
//};

/**
 * 工具方法
 * 返回值 char* 这个代表char数组的首地址
 *  Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
 */
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
	char* rtn = NULL;
	jclass  clsstring = env->FindClass("java/lang/String");
	jstring strencode = env->NewStringUTF("utf-8");
	jmethodID mid = env->GetMethodID(clsstring, "getBytes","(Ljava/lang/String;)[B");
	jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid,strencode);
	jsize alen = env->GetArrayLength(barr);
	jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0) {
		rtn = (char*) malloc(alen + 1);
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0);
	return rtn;
}

JNIEXPORT jstring JNICALL Java_com_shuqi_application_ReadLocalBookFormat_getBookFormat(
		JNIEnv* env, jclass clazz, jstring jInfo) {
	int error = 0;
	char* ps = Jstring2CStr(env, jInfo);
	char const*retString = fileEncodingString(ps,error);
	return env->NewStringUTF(retString);
}
